#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright @ 2014 OPS, Qunar Inc. (qunar.com)
#
# Author: tingfang.bao <tingfang.bao@qunar.com>
# DateTime: 15-3-9 上午11:02
"""
Flask　内部WSGI的工作原理

def wsgi_app(self, environ) :
    with self.request_context(environ) :
        try:
            response = self. full_dispatch_request()
        except Exception, e:
            response = self. make_response(self. handle_exception(e) )
        return response(environ, start_response)

request_context：创建了request context，在push后，也就创建了application context,也就可以访问上下文本地对象了
内部工作机制类似一个stack，栈顶是当前活动的request,在popping后，会调用teardown_request()方法

Flask请求处理流程
    １．　请求前：每个before_request()都会被执行，如果其中一个返回了response，其他before_request都不会被执行。返回的response会作为结果返回
    ２．　顺利完成步骤１，请求进入正常的处理环节，通过路由系统，进入对应视图函数，这非常正常
    ３．  步骤２的返回结果，转换成response对象，交给after_request()函数执行，它们都有机会修改返回结果
    ４．  最后,会调用teardown_request(),这个一定会被执行的，即使发生了异常或者根本没有执行before_request()函数

Flask出现错误后：
    生产模式下：调用500　error handler
    开发模式下：直接抛给WSGI server

Flask中的代理对象：主要是寻找当前线程中正确的对象
获取底层的对象
app = current_app._get_current_object()
my_signal.send(app)

保留错误信息
主要使用变量：PRESERVE_CONTEXT_ON_EXCEPTION,该变量与DEBUG关联，如果debug=true,preserve_context_on_exception=true
"""
from flask import Flask, request, url_for, current_app

app = Flask(__name__)
app.name = 'request context demo'


def redirect_url():
    """
    这里只是一个普通方法，
    关键是要明确，在什么情况下，可以访问到request对象
    """
    return request.args.get('next') or request.referrer or url_for('index')

# 方式１：一步一步创建request context
# 1. 必须先要构建一个request_context
ctx = app.test_request_context('/?next=http://www.baidu.com')

# 如果调用下面一句，会出错，因为还没有push进request context
# print current_app.name

# 2. 必须将context　push进去，才会生效，这也说明这里存在一个stack,同时也会创建application_context
ctx.push()

# 3. 可以正常访问request对象
print redirect_url()

# 说明在push进入了 request context后，就创建了application_context,也就使用一系列的上下文本地对象了
print current_app.name

# ４. pop之后，request context失效
ctx.pop()

# 5. 如果调用下面的语句，这里就会出错了
# print redirect_url()

# 方式２：　使用with语句
with app.test_request_context("/?next=http://www.sohu.com"):
    print redirect_url()